#pragma once
#include "Common.h"
#include "Task.h"
#include<vector>
#include<thread>
#include<mutex>
#include<condition_variable>
#include<queue>

template<typename T>
class ThreadPool
{
private:
    std::vector<std::thread> v;
    std::queue<T> q;
    std::mutex mtx;
    std::condition_variable cv;
    int size;
public:
    ThreadPool(int num = 5):size(num),v(num)
    {
        for(int i = 0; i < num; ++i)
        {
            v[i] = std::thread(&ThreadPool::Loop,this);
            v[i].detach();
        }
    }
    void Push(T& t)
    {
        std::unique_lock<std::mutex> ul(mtx);
        q.push(t);
        cv.notify_one();
    }
    void Pop(T& t)
    {
        t = q.front();
        q.pop();
    }
    void Loop()
    {
        while(true)
        {
            std::unique_lock<std::mutex> ul(mtx);
            while(q.empty() == true)
                cv.wait(ul);
            T t;
            Pop(t);
            ul.unlock();
            t.Execute();
        }
    }
};